﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GBPVRX2.UiSupport;
using System.Globalization;
using GBPVRX2;
using System.IO;
using System.Xml;
using System.Drawing;
using GBPVRLibrary.UtilityLibrary;
using System.Collections;

namespace GBPVRLibrary.ControlLibrary
{
    public class OnScreenKeyboard : GuiElement
    {
        protected SkinHelper2 OSKSkinHelper { get; set; }

        private List<OnScreenKeyboardRow> Rows { get; set; }

        protected bool ShiftDown = false;
        protected bool CapsLockOn = false;
        protected bool SybmolsOn = false;

        protected int SelectedRow { get; set; }
        protected int SelectColumn { get; set; }

        public enum KeyCommand
        {
            InputKey, Done, Space, Backspace, Shift, CapsLock, Symbols, Cancel, Clear, Left, Right
        }

        public OnScreenKeyboard()
        {
            this.Visible = false;
            //SkinHelper.get
            string code = CultureInfo.CurrentCulture.TwoLetterISOLanguageName;
            string dir = PluginHelper.GetSkinRootDirectory();
            if (!dir.EndsWith(@"\"))
                dir += @"\";
            dir += @"GBPVRLibrary\";
            dir = dir.Replace(@"\skin\", @"\skin2\"); // not the best, but getskinrootdirectory returns the GBPVR (skin) directory and not skin2.
            if (File.Exists(dir + "OnScreenKeyboard-" + code + ".xml"))
                OSKSkinHelper = new SkinHelper2(@"GBPVRLibrary\OnScreenKeyboard-" + code + ".xml");
            else
                OSKSkinHelper = new SkinHelper2(@"GBPVRLibrary\OnScreenKeyboard.xml");

            XmlNode node = OSKSkinHelper.getPlacementNode("Keys");
            PointF loc = OSKSkinHelper.getPlacementPos("Keys");
            PointF padding = OSKSkinHelper.getPlacementAttributePos("Keys", "padding");
            Rows = new List<OnScreenKeyboardRow>();
            foreach (XmlNode rNode in node.ChildNodes)
            {
                OnScreenKeyboardRow row = new OnScreenKeyboardRow();
                float? buttonHeight = null;                
                PointF keyLoc = new PointF(loc.X, loc.Y);
                foreach (XmlNode kNode in rNode.ChildNodes)
                {
                    string Image = kNode.Attributes["Image"].Value;
                    OnScreenKeyboardKey key = new OnScreenKeyboardKey();
                    RectangleF size = OSKSkinHelper.getPlacementRect(String.Format("{0}-Normal", Image));
                    if (buttonHeight == null)
                        buttonHeight = size.Height;

                    key.Selected = new UiStatic(OSKSkinHelper, String.Format("{0}-Selected", Image), key.Parameters);
                    key.Selected.SetLocation(keyLoc);
                    key.Normal = new UiStatic(OSKSkinHelper, String.Format("{0}-Normal", Image), key.Parameters);
                    key.Normal.SetLocation(keyLoc);
                    if (kNode.Attributes["command"] != null) // its a command key
                    {
                        key.Sybmol = kNode.Attributes["command"].Value;
                        key.Command = (KeyCommand)Enum.Parse(typeof(KeyCommand), key.Sybmol);
                    }
                    else // its a normal key
                    {
                        key.Command = KeyCommand.InputKey;
                        key.LowerCase = kNode.Attributes["lowerCase"].Value;
                        key.UpperCase = kNode.Attributes["upperCase"].Value;
                        key.Sybmol = kNode.Attributes["symbol"].Value;
                    }
                    keyLoc.X += size.Width + padding.X;
                    row.Keys.Add(key);
                }
                Rows.Add(row);
                loc.Y += buttonHeight.Value + padding.Y;
            }
        }

        protected override void Render(System.Collections.ArrayList RenderList, ref bool RequiresMoreRendering)
        {
            int r = 0;
            foreach (OnScreenKeyboardRow row in this.Rows)
            {
                int c = 0;
                foreach (OnScreenKeyboardKey key in row.Keys)
                {
                    if (key.Command != KeyCommand.InputKey)
                        key.Parameters["@KeyChar"] = key.Command.ToString();
                    else if (CapsLockOn)
                        key.Parameters["@KeyChar"] = ShiftDown ? key.LowerCase : key.UpperCase;
                    else if (SybmolsOn)
                        key.Parameters["@KeyChar"] = key.Sybmol;
                    else
                        key.Parameters["@KeyChar"] = ShiftDown ? key.UpperCase : key.LowerCase;
                    if (r == SelectedRow && c == SelectColumn)
                    {
                        key.Selected.SetArgs(key.Parameters);
                        RenderList.AddRange(key.Selected.GetRenderList());
                    }
                    else
                    {
                        key.Normal.SetArgs(key.Parameters);
                        RenderList.AddRange(key.Normal.GetRenderList());
                    }
                    c++;
                }
                r++;
            }
        }

        public override bool OnKeyDown(System.Windows.Forms.KeyEventArgs e)
        {
            switch (KeyMapper.GetControlKey(e))
            {
                case KeyMapper.ControlKey.DirectionRight:
                    if (SelectColumn + 1 >= Rows[SelectedRow].Keys.Count)
                        SelectColumn = 0;
                    else
                        SelectColumn++;
                    return true;
                case KeyMapper.ControlKey.DirectionLeft:
                    if (SelectColumn - 1 >= 0)
                        SelectColumn--;
                    else
                        SelectColumn = Rows[SelectedRow].Keys.Count - 1;
                    return true;
                case KeyMapper.ControlKey.DirectionDown:
                    if (SelectedRow + 1 >= Rows.Count)
                        SelectedRow = 0;
                    else
                        SelectedRow++;
                    if (SelectColumn >= Rows[SelectedRow].Keys.Count)
                        SelectColumn = Rows[SelectedRow].Keys.Count - 1;
                    return true;
                case KeyMapper.ControlKey.DirectionUp:
                    if (SelectedRow - 1 >= 0)
                        SelectedRow--;
                    else
                        SelectedRow = Rows.Count - 1;
                    if (SelectColumn >= Rows[SelectedRow].Keys.Count)
                        SelectColumn = Rows[SelectedRow].Keys.Count - 1;
                    return true;
            }
            // need to read the keyboard directly
            if (!e.Control && !e.Alt)
            {
                switch (e.KeyCode)
                {
                    case System.Windows.Forms.Keys.CapsLock:
                        CapsLockOn = !CapsLockOn; // need to get it from the system!
                        return true;
                }
            }
            return base.OnKeyDown(e);
        }
    }

    class OnScreenKeyboardRow
    {
        public OnScreenKeyboardRow() { Keys = new List<OnScreenKeyboardKey>(); }

        public List<OnScreenKeyboardKey> Keys { get; set; }
    }

    class OnScreenKeyboardKey
    {
        public UiStatic Normal { get; set; }
        public UiStatic Selected { get; set; }

        public string UpperCase { get; set; }
        public string LowerCase { get; set; }
        public string Sybmol { get; set; }
        public Hashtable Parameters { get; set; }

        public OnScreenKeyboard.KeyCommand Command { get; set; }

        public OnScreenKeyboardKey() { Parameters = new Hashtable(); }

        
    }
}
